package org.jing.core.logger.logback;

import ch.qos.logback.classic.Level;
import org.jing.core.logger.itf.JingLoggerLevelItf;
import org.jing.core.util.StringUtil;

import java.lang.reflect.Constructor;

/**
 * Description: <br>
 *
 * @author bks <br>
 * @since 2021-08-16 <br>
 */
@SuppressWarnings({ "unused", "WeakerAccess" })
public class LoggerLevel implements JingLoggerLevelItf {
    public static final LoggerLevel ALL = new LoggerLevel(Level.ALL);

    public static final LoggerLevel TRACE = new LoggerLevel(Level.TRACE);

    public static final LoggerLevel DEBUG = new LoggerLevel(Level.DEBUG);

    public static final LoggerLevel INFO = new LoggerLevel(Level.INFO);

    public static final LoggerLevel WARN = new LoggerLevel(Level.WARN);

    public static final LoggerLevel IMP  = new LoggerLevel(39999, "IMP");

    public static final LoggerLevel SQL = new LoggerLevel(39999, "SQL");

    public static final LoggerLevel ERROR = new LoggerLevel(Level.ERROR);

    public static final LoggerLevel FATAL = new LoggerLevel(50000, "FATAL");

    public static final LoggerLevel OFF = new LoggerLevel(Level.OFF);

    public static final LoggerLevel DEFAULT_LEVEL = DEBUG;

    private final Level level;

    public LoggerLevel(int level, String levelStr) {
        this.level = createLevel(level, levelStr);
    }

    public LoggerLevel(Level level) {
        this.level = level;
    }

    private static Level createLevel(int level, String levelStr) {
        try {
            Constructor[] constructors = Level.class.getDeclaredConstructors();
            Constructor constructor = Level.class.getDeclaredConstructor(int.class, String.class);
            constructor.setAccessible(true);
            return (Level) constructor.newInstance(level, levelStr);
        }
        catch (Throwable ignored) {
            return null;
        }
    }

    @Override public boolean isGreaterOrEquals(JingLoggerLevelItf e) {
        return level.isGreaterOrEqual(((LoggerLevel) e).level);
    }

    public static LoggerLevel toLevel(String levelStr) {
        return toLevel(levelStr, DEFAULT_LEVEL);
    }

    public static LoggerLevel valueOf(String levelStr) {
        return toLevel(levelStr, DEFAULT_LEVEL);
    }

    public static LoggerLevel toLevel(int val) {
        return toLevel(val, DEFAULT_LEVEL);
    }

    public static LoggerLevel toLevel(int val, LoggerLevel defaultLevel) {
        switch(val) {
            case -2147483648:
                return ALL;
            case 5000:
                return TRACE;
            case 10000:
                return DEBUG;
            case 20000:
                return INFO;
            case 30000:
                return WARN;
            case 39999:
                return IMP;
            case 40000:
                return ERROR;
            case 2147483647:
                return OFF;
            default:
                return defaultLevel;
        }
    }

    public static LoggerLevel toLevel(String levelStr, LoggerLevel defaultLevel) {
        levelStr = StringUtil.ifEmpty(levelStr).toUpperCase();
        switch (levelStr) {
            case "ALL": return ALL;
            case "TRACE": return TRACE;
            case "DEBUG": return DEBUG;
            case "INFO": return INFO;
            case "WARN": return WARN;
            case "IMP": return IMP;
            case "SQL": return SQL;
            case "ERROR": return ERROR;
            case "FATAL": return FATAL;
            case "OFF": return OFF;
            default: return DEFAULT_LEVEL;
        }
    }

    public Level getLevel() {
        return level;
    }
}
